﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Text;
using System.Data;
using System.IO;
using System.Windows.Forms; 

using Microsoft.AnalysisServices.AdomdClient;
using Microsoft.AnalysisServices.Xmla;
using System.Linq;
using System.Xml.Linq;


namespace BILab.Technical.BI.Facade
{
    public class XMLAMDFacade : IMultidimensionalFacade
    {

        #region Connectivity
        private string _connectionString;
        private AdomdConnection _mdConn;
        private XmlaClient _xmlaWs = new XmlaClient();
        private string _catalog;

        public void Close()
        {
            if (_mdConn != null)
            {
                if (_mdConn.State == ConnectionState.Open)
                {
                    _mdConn.Close();
                }
            }
        }

        public bool Connect(string connString)
        {
            Boolean connected = false;
            this.ConnectionString = connString;

            _xmlaWs.Connect(connString);            
            if ( _xmlaWs.GetConnectionState(true) == ConnectionState.Open)
            {
                connected = true;
            }
            return connected;
        }

        public string ConnectionString
        {
            get 
            {  return _connectionString;     }
            set 
            {
                _catalog = this.getCatalog(value);                
                _connectionString = value; 
            }
        }
        #endregion

        #region Query
        public Microsoft.AnalysisServices.AdomdClient.CellSet getCellSet(string mdxQuery)
        {
            return null;
        }

        public System.Data.DataSet getDataset(string mdxQuery)
        {
            return null;
        }
        #endregion

        #region extra method
        public List<string> getDatasources()
        {
            return null;
        }

        private string getCatalog(string connString)
        {
            string r_str = null;

            char[] semicolSep = new char[1]{';'};
            char[] equalSep   = new char[1] { '=' };

            string[] param = connString.Split(semicolSep);
            string element = null;

            for (int i = 0; i < param.Length; i++)
            {
                element = param[i];
                if (element.ToUpper().IndexOf("CATALOG") > 0)
                {
                    r_str = element.Split(equalSep)[1];
                }
            }
            return r_str;
        }

        private string getLevelUName(string dimName, string hierName, string levName)
        {
            hierName = this.getHierarchyUName(dimName, hierName);
            dimName = this.getDimensionUName(dimName);
            
            StringBuilder sb = new StringBuilder();

            if (levName.StartsWith("[") && levName.EndsWith("]") )
            {              
                sb.Append(hierName);
                sb.Append(".");
                sb.Append(levName);

            }
            else
            {
                sb.Append(hierName);
                sb.Append(".[");
                sb.Append(levName);
                sb.Append("]");
            }
            return sb.ToString();
        }

        private string getHierarchyUName(string dimName,string hierName)      
        {
            dimName = this.getDimensionUName(dimName);
            StringBuilder sb = new StringBuilder();

            if (hierName.StartsWith("[") && hierName.EndsWith("]"))
            {
                sb.Append(dimName);
                sb.Append(".");
                sb.Append(hierName);                
            }
            else
            {
                sb.Append(dimName);
                sb.Append(".[");                
                sb.Append(hierName);
                sb.Append("]");                
            }
            return sb.ToString();
        }
        private string getDimensionUName(string dimName)
        {
            if (dimName.StartsWith("[") && dimName.EndsWith("]"))
            {
                return dimName;
            }
            else
            {
                StringBuilder sb = new StringBuilder("[");
                sb.Append(dimName);
                sb.Append("]");
                return sb.ToString();
            }
        }
        #endregion

        #region Metadata
public System.Collections.Generic.List<string> getCubeList()
{
    List<string> r_list = new List<string>();
    string command = XmlaRessource.getCubeList;
    command = command.Replace("$CATALOG",_catalog);

    string xmlaResult = _xmlaWs.Send(command, null);
    
    XElement xResult = XElement.Load(new StringReader(xmlaResult));
    XNamespace ns = XNamespace.Get("urn:schemas-microsoft-com:xml-analysis:rowset");
    
    IEnumerable<string> cubeList =
        from elt in xResult.Elements(ns + "root").Elements(ns + "row").Elements(ns + "CUBE_NAME")
        select elt.Value
        ;

    foreach (string str in cubeList)
    {
        r_list.Add(str);
    }
    return r_list;
}

public System.Collections.Generic.List<string> getDimension(string cubeName)
{
    List<string> r_list = new List<string>();
    string command = XmlaRessource.getDimensionList;
    //command = command.Replace("$CATALOG", _catalog);
    command = command.Replace("$CUBE", cubeName);        

    string xmlaResult = _xmlaWs.Send(command, null);

    XElement xResult = XElement.Load(new StringReader(xmlaResult));
    XNamespace ns = XNamespace.Get("urn:schemas-microsoft-com:xml-analysis:rowset");

    IEnumerable<string> cubeList =
        from elt in xResult.Elements(ns + "root").Elements(ns + "row").Elements(ns + "DIMENSION_NAME")
        select elt.Value
        ;

    foreach (string str in cubeList)
    {
        r_list.Add(str);
    }
    return r_list;
}

        public System.Collections.Generic.List<string> getHierarchies(string cubeName, string dimName)
        {
            List<string> r_list = new List<string>();
            string command = XmlaRessource.getHierachies;
            command = command.Replace("$CATALOG", _catalog);
            command = command.Replace("$CUBE", cubeName);
            
            dimName = this.getDimensionUName(dimName);
            command = command.Replace("$DIMENSION", dimName);           

            string xmlaResult = _xmlaWs.Send(command, null);

            XElement xResult = XElement.Load(new StringReader(xmlaResult));
            XNamespace ns = XNamespace.Get("urn:schemas-microsoft-com:xml-analysis:rowset");

            IEnumerable<string> cubeList =
                from elt in xResult.Elements(ns + "root").Elements(ns + "row").Elements(ns + "HIERARCHY_NAME")
                select elt.Value
                ;

            foreach (string str in cubeList)
            {
                r_list.Add(str);
            }
            return r_list;
        }

        public System.Collections.Generic.List<string> getLevels(string cubeName, string dimName, string hierName)
        {
            List<string> r_list = new List<string>();

           
            hierName = this.getHierarchyUName(dimName, hierName);
            dimName = this.getDimensionUName(dimName);

            string command = XmlaRessource.getLevels;
            command = command.Replace("$CATALOG", _catalog);
            command = command.Replace("$CUBE", cubeName);
            command = command.Replace("$DIMENSION", dimName);
            command = command.Replace("$HIERARCHY", hierName);

            //xmlaWs.Disconnect();
            //_xmlaWs.Connect(this.ConnectionString);
            string xmlaResult = _xmlaWs.Send(command, null);

            XElement xResult = XElement.Load(new StringReader(xmlaResult));
            XNamespace ns = XNamespace.Get("urn:schemas-microsoft-com:xml-analysis:rowset");

            IEnumerable<string> cubeList =
                from elt in xResult.Elements(ns + "root").Elements(ns + "row").Elements(ns + "LEVEL_NAME")
                select elt.Value
                ;

            foreach (string str in cubeList)
            {
                r_list.Add(str);
            }
            return r_list;
        }

        public System.Collections.Generic.List<string> getMembers(string cubeName, string dimName, string hierName, string levelName)
        {
            List<string> r_list = new List<string>();

            levelName = this.getLevelUName(dimName, hierName, levelName);
            hierName = this.getHierarchyUName(dimName, hierName);
            dimName = this.getDimensionUName(dimName);
            
            

            string command = XmlaRessource.getMembers;
            command = command.Replace("$CATALOG", _catalog);
            command = command.Replace("$CUBE", cubeName);
            command = command.Replace("$DIMENSION", dimName);
            command = command.Replace("$HIERARCHY", hierName);
            command = command.Replace("$LEVEL", levelName);


            string xmlaResult = _xmlaWs.Send(command, null);

            XElement xResult = XElement.Load(new StringReader(xmlaResult));
            XNamespace ns = XNamespace.Get("urn:schemas-microsoft-com:xml-analysis:rowset");

            IEnumerable<string> cubeList =
                from elt in xResult.Elements(ns + "root").Elements(ns + "row").Elements(ns + "MEMBER_NAME")
                select elt.Value
                ;

            foreach (string str in cubeList)
            {
                r_list.Add(str);
            }
            return r_list;

        }
        #endregion

        #region treenode Mgt to UI
        public System.Windows.Forms.TreeNode GetDimensionTree(string cubeName)
        {
            TreeNode nodes = new TreeNode("Dimension");
            string dimName;
            // Step 1
            List<string> dim = this.getDimension(cubeName);

            // Step 2
            for (int i = 0; i < dim.Count; i++)
            {
                dimName = dim[i];
                TreeNode dimNode = new TreeNode(dimName, 1, 1);

                /* populates hierarchies for a given dimension*/
                // Step 3
                this.getHierarchyTree(ref dimNode, cubeName, dimName);

                /* populates Hierarchy list */
                nodes.Nodes.Add(dimNode);
            }
            return nodes;
        }

        private void getHierarchyTree(ref TreeNode r_parentNode, string cubeName, string DimName)
        {
            //Step 1
            List<string> hier = this.getHierarchies(cubeName, DimName);

            string hierName;

            // Step 2
            for (int i = 0; i < hier.Count; i++)
            {
                hierName = hier[i];
                TreeNode hier_node = new TreeNode(hierName, 2, 2);

                // Step 3
                /* populates the levels for that given hierarchy */
                this.getLevelTree(ref hier_node, cubeName, DimName, hierName);

                // Step 4
                r_parentNode.Nodes.Add(hier_node);
            }
        }

        private void getLevelTree(ref TreeNode r_parentNode, string cubeName, string dimName, string hierName)
        {
            // step 1
            List<string> level = this.getLevels(cubeName, dimName, hierName);

            string levelName;
            // Step 2
            for (int i = 0; i < level.Count; i++)
            {
                levelName = level[i];
                TreeNode tempNode = new TreeNode(levelName, 3, 3);
                tempNode.Nodes.Add("dummy");
                // Step 3
                this.getMemberTree(ref tempNode, cubeName, dimName, hierName, levelName);

                // Step 4
                r_parentNode.Nodes.Add(tempNode);
            }
        }

        public void getMemberTree(ref System.Windows.Forms.TreeNode r_parentNode, string cubeName, string dimName, string hierName, string levelName)
        {
             List<string> members = this.getMembers(cubeName, dimName, hierName, levelName);
            string memberName;

            for (int i = 0; i < members.Count; i++)
            {
                memberName = members[i];
                TreeNode tempNode = new TreeNode(memberName,4,4);
                r_parentNode.Nodes.Add(tempNode);
            }            

        }
        #endregion

    }
}
